#include "optimization.h"
#include "utility.h"
#include <algorithm>
#include "extendedverilogparser.h"
#include "timer_interface.h"
#include "time.h"
#include "thread.h"
#include <ctime>
#include <sstream>


#include <boost/random/uniform_int.hpp>
#include <boost/random/mersenne_twister.hpp>

#include "validate.cpp"
#include "parser_helper.h"
#include "extendedlibparser.h"
#include "extendedtimingparser.h"
#include "extendedspefparser.h"
#include "extendedsdcparser.h"
#include "extendedverilogparser.h"
#include "circuitgraph.hpp"

//global variables, Min
CircuitGraph* graphInPtr;
ExtendedVerilogParser* vpPtr;
ExtendedSdcParser* sdcPtr;
ExtendedLibParser* lpPtr;
ExtendedTimingParser* tpPtr;
//vector<string> optList;

using namespace std ;
typedef boost::mt19937 gen;


bool lessLeakage(const string &s1, const string &s2)
{
        LibParserCellInfo *LPCI1, *LPCI2;
        LPCI1 = &(lpPtr->mapStandardLibraryCells[s1]);
        LPCI2 = &(lpPtr->mapStandardLibraryCells[s2]);
        
        return (LPCI1->leakagePower < LPCI2->leakagePower);
}

void minLeakage (CircuitGraph& graphIn)
{
        int i,j;
        int numberOfCells;
        LibParserCellInfo *LPCI;
        
        double temp_leakage;
        string selected_cell_name;
        cout << "Choosing minimum leakage cells...." << endl;
        
        int vn = boost::num_vertices(graphIn) ;
        cout << "Number of gates: " << vn << endl ;
        
        for( i = 0; i < vn; i++)
        {               
                if(graphIn[i].gateType == 2)
                {
                        //sort the cells of same footprint in less leakage order
                        std::sort(graphIn[i].listOfCells.begin(),graphIn[i].listOfCells.end(),lessLeakage);
                        graphIn[ i ].cellName = graphIn[i].listOfCells[0];
                        graphIn[ i ].previousIndex = 0; // this is important
                }
        }
}


bool moreViolation(const int i1, const int i2)
{
        return ((*graphInPtr)[i1].Slew_Violation + (*graphInPtr)[i1].Slack_Violation + (*graphInPtr)[i1].Cap_Violation > 
                (*graphInPtr)[i2].Slew_Violation + (*graphInPtr)[i2].Slack_Violation + (*graphInPtr)[i2].Cap_Violation);
}

pair<string, string> assignDir(long dir, long tot_piece_num, string footprint){
        
        // first, we assume all block is rectangular and the area of all
        // cells is 12 = 4 * 3
        double x_loc = 40, y_loc = 40;
        const double pi = 3.1415926;
        double direction = (double)dir / (double)tot_piece_num;
        double Direction = direction * 360.0;
        
        //cout << "Direction is " << Direction << endl;
        //cout << "tan (45) = " << tan(45 * pi / 180) << endl;
        if(Direction >= 0.0 && Direction < 45.0){
                x_loc = 4.0; 
                y_loc = 4.0 * tan(Direction * pi / 180.0);
        }
        else if(Direction >= 45.0 && Direction < 90.0){
                x_loc = 3.0 / tan(Direction) * pi / 180.0;
                y_loc = 3.0;
        }
        else if(Direction >= 90.0 && Direction < 135.0){
                x_loc = 3.0 / tan(Direction * pi / 180.0);
                y_loc = 3.0;
        }
        else if(Direction >= 135.0 && Direction < 180.0){
                x_loc = 4.0; 
                y_loc = 4.0 * tan(Direction * pi / 180.0);
        }
        else if(Direction >= 180.0 && Direction < 225.0){
                x_loc = 4.0; 
                y_loc = 4.0 * tan(Direction * pi / 180.0);
        }
        else if(Direction >= 225.0 && Direction < 270.0){
                x_loc = 3.0 / tan(Direction * pi / 180.0);
                y_loc = 3.0;
        }
        else if(Direction >= 270.0 && Direction < 315.0){
                x_loc = 3.0 / tan(Direction * pi / 180.0);
                y_loc = 3.0;
        }
        else{
                x_loc = 4.0; 
                y_loc = 4.0 * tan(Direction * pi / 180.0);
        }
        
        stringstream ss, ss1;
        ss << fixed; ss1 << fixed;
        ss << setprecision (1) << x_loc;
        ss1 << setprecision (1) << y_loc;
        
        if(x_loc == 40.0 || y_loc == 40.0){
                cout << "No Way!" << endl;
                cout << " dir is " << dir << endl;
                cout << " total piece is " << tot_piece_num << endl;
                cout << setprecision (1) << x_loc << endl;
                cout << setprecision (1) << y_loc << endl;
                cin.get();
        }
        
        return make_pair(ss.str(), ss1.str());
}

void assignPinDir(CircuitGraph& graphIn){
        
        int i, j, flag;
        pair<string, string> X_Y_loc;
        
        //std::vector<std::string> :: iterator it_vec;
        std::vector<vertex_descriptor> :: iterator it_vec;
        boost::graph_traits<CircuitGraph>::vertex_iterator vi, vi_end ;
        std::map < std::string, std::pair<std::string, pinDirection_t> >:: iterator it; 
        
        for (boost::tie(vi, vi_end) = boost::vertices(graphIn) ; vi != vi_end ; ++vi){
                
                i = 0; flag = 0;
                vertex_descriptor in = (*vi) ;
                if(graphIn[ in ].gateType == 0 || graphIn[ in ].gateType == 1)
                        continue;
                
                long count_edge = 0;
                for( it = graphIn[ in ].mapPinNetDirection.begin(); it != graphIn[ in ].mapPinNetDirection.end(); it++)
                        for(j = 0; j < vpPtr->verilogConnectivity.size(); j++)
                                if(vpPtr->verilogConnectivity[j].netName == (*it).second.first)
                                        count_edge += vpPtr->verilogConnectivity[j].targetVertices.size() + 1;
                        
                for( it = graphIn[ in ].mapPinNetDirection.begin(); it != graphIn[ in ].mapPinNetDirection.end(); it++)
                {
                        X_Y_loc = assignDir(i, count_edge, "NULL");
                        //X_Y_loc = assignDir(i, graphIn[ in ].mapPinNetDirection.size(), "NULL");
                        for(j = 0; j < vpPtr->verilogConnectivity.size(); j++){
                                if(vpPtr->verilogConnectivity[j].netName == (*it).second.first){
                                        //if((*it).first == "ck")
                                        //cout << " X Y location is " << X_Y_loc.first << "\t" << X_Y_loc.second << endl;
                                        
                                        if( in == vpPtr->verilogConnectivity[j].sourceVertex )
                                        //if( in == vpPtr->verilogConnectivity[j].sourceVertex && (*it).first == vpPtr->verilogConnectivity[j].sourcePin )
                                                vpPtr->verilogConnectivity[j].sourceDir = X_Y_loc;
                                        else{
                                                
                                                it_vec = std::find(vpPtr->verilogConnectivity[j].targetVertices.begin(), 
                                                                   vpPtr->verilogConnectivity[j].targetVertices.end(), in);
                                                //cout << " pin name is " << (*it).first << endl;
                                                assert(it_vec != vpPtr->verilogConnectivity[j].targetVertices.end());
                                                //cout << "size is " << vpPtr->verilogConnectivity[j].targetDirs.size() << endl;
                                                vpPtr->verilogConnectivity[j].targetDirs[distance(vpPtr->verilogConnectivity[j].targetVertices.begin(), it_vec)] = X_Y_loc;
                                        }
                                        
                                        flag = 1;
                                        break;
                                }
                        }
                        
                        if(flag != 1){
                        //if(flag != 1 && ((*it).first != "in") && ((*it).first != "out")){
                                cout << "Cell name is " << graphIn[ in ].instanceName << endl;
                                cout << " Net name is " << (*it).first << endl;
                                cin.get();
                        }
                        
                        i++;
                }
        }
}

double violationCheck(CircuitGraph& graphIn, bool write_to_file)
{
        //ofstream out("HEHE");
        int count_cap_vio = 0;
        int count_slew_vio = 0;
        int count_slack_vio = 0;
        LibParserCellInfo *LPCI;
        LibParserCellInfo *LPCI_;
        double T_Output_Cap;
        double temp = 0.0;
        double Cap_Violation = 0.0;
        double Slack_Violation = 0.0;
        double Slew_Violation = 0.0;
        lpPtr->default_max_transition = 300.0;// same for all
        
        vector<LibParserPinInfo>::iterator it;
        boost::graph_traits<CircuitGraph>::vertex_iterator vi, vi_end ;
	boost::graph_traits<CircuitGraph>::out_edge_iterator oi, oi_end;

        for (boost::tie(vi, vi_end) = boost::vertices(graphIn) ; vi != vi_end ; ++vi)
	{
                
                vertex_descriptor in = (*vi) ;
                graphIn[ in ].Slew_Violation = 0.0;
                graphIn[ in ].Slack_Violation = 0.0;
                graphIn[ in ].Cap_Violation = 0.0;

                graphIn[ in ].Slew_Redundancy = 0.0;
                graphIn[ in ].Slack_Redundancy = 0.0;
                graphIn[ in ].Cap_Redundancy = 0.0;
                
                LPCI = &(lpPtr->mapStandardLibraryCells[ graphIn[ in ].cellName ]);
                
                if(graphIn[ in ].gateType == 0 || graphIn[ in ].gateType == 1)
                        continue;

                //check the slew violation, for input pins of
                //Combinational and Sequential cells
                if(graphIn[ in ].gateType != 0 && graphIn[ in ].gateType != 1)
                {
                        for(it = LPCI->pins.begin(); it != LPCI->pins.end(); it++)
                                if(it->name != "o")//not the output pins
                                {
                                        double temp_violation = 0.0;
                                        double temp_slack_violation = 0.0;
                                        double temp_redundancy = 0.0;
                                        double temp_slack_redundancy = 0.0;
                                        string tmp_name = graphIn[ in ].instanceName + "/" + it->name;
                                
                                        if(tpPtr->PinsTiming[tmp_name].riseTransition > lpPtr->default_max_transition)
                                                temp_violation += tpPtr->PinsTiming[tmp_name].riseTransition - lpPtr->default_max_transition;
                                
                                        if(tpPtr->PinsTiming[tmp_name].fallTransition > lpPtr->default_max_transition)
                                                temp_violation += tpPtr->PinsTiming[tmp_name].fallTransition - lpPtr->default_max_transition;
                                
                                        if(tpPtr->PinsTiming[tmp_name].riseSlack < 0)
                                                temp_slack_violation += abs(tpPtr->PinsTiming[tmp_name].riseSlack);
                                        else
                                                temp_slack_redundancy += abs(tpPtr->PinsTiming[tmp_name].riseSlack);
                                
                                        if(tpPtr->PinsTiming[tmp_name].fallSlack < 0)
                                                temp_slack_violation += abs(tpPtr->PinsTiming[tmp_name].fallSlack);
                                        else
                                                temp_slack_redundancy += abs(tpPtr->PinsTiming[tmp_name].fallSlack);
                                
                                        graphIn[ in ].Slew_Violation += temp_violation;                                
                                        graphIn[ in ].Slack_Violation += temp_slack_violation;                                
                                        graphIn[ in ].Slack_Redundancy += temp_slack_redundancy;
                                        
                                        Slew_Violation += temp_violation;
                                }
                
                        //check the slack violation, for sequential gates
                        if(graphIn[ in ].gateType == 3)
                        {
                                for(it = LPCI->pins.begin(); it != LPCI->pins.end(); it++)
                                        if(it->name != "o" && it->name != "ck")//not the output pins
                                        {
                                                double temp_violation = 0.0;
                                                double temp_slack_redundancy = 0.0;
                                                string tmp_name = graphIn[ in ].instanceName + "/" + it->name;
                                        
                                                if(tpPtr->PinsTiming[tmp_name].riseSlack < 0)
                                                        temp_violation += abs(tpPtr->PinsTiming[tmp_name].riseSlack);
                                                else
                                                        temp_slack_redundancy += abs(tpPtr->PinsTiming[tmp_name].riseSlack);
                                                
                                                if(tpPtr->PinsTiming[tmp_name].fallSlack < 0)
                                                        temp_violation += abs(tpPtr->PinsTiming[tmp_name].fallSlack);
                                                else
                                                        temp_slack_redundancy += abs(tpPtr->PinsTiming[tmp_name].fallSlack);

                                                //for sequential circuit, should be
                                                //only one net connect to DFF input
                                        
                                                graphIn[ in ].Slack_Violation += temp_violation;
                                                graphIn[ in ].Slack_Redundancy += temp_slack_redundancy;
                                                Slack_Violation += temp_violation;
                                        }
                        }
                }
                
                //check the output cap violation
                temp = 0.0;
                T_Output_Cap = 0.0;
                for ( boost::tie(oi, oi_end) = boost::out_edges(in, graphIn) ; oi != oi_end ; ++oi )
                {
                        //finding the pin connect to PI, for driver,
                        //instance name and pin name and cell name are same
                        double temp_slack_violation = 0.0;
                        double temp_slew_violation = 0.0;
                        double temp_slack_redundancy = 0.0;
                
                        //check the slack and slew violation, for POs
                        if(graphIn[target((*oi), graphIn)].gateType == 1)//is PO
                        {
                                
                                if(tpPtr->PortsTiming[graphIn[(*oi)].netName].riseSlack < 0)
                                        temp_slack_violation += abs(tpPtr->PortsTiming[graphIn[(*oi)].netName].riseSlack);
                                else
                                        temp_slack_redundancy += abs(tpPtr->PortsTiming[graphIn[(*oi)].netName].riseSlack);
                                       
                                if(tpPtr->PortsTiming[graphIn[(*oi)].netName].fallSlack < 0)
                                        temp_slack_violation += abs(tpPtr->PortsTiming[graphIn[(*oi)].netName].fallSlack);
                                else
                                        temp_slack_redundancy += abs(tpPtr->PortsTiming[graphIn[(*oi)].netName].fallSlack);
                                
                                if(tpPtr->PinsTiming[graphIn[(*oi)].netName].riseTransition > lpPtr->default_max_transition)
                                        temp_slew_violation += tpPtr->PinsTiming[graphIn[(*oi)].netName].riseTransition - lpPtr->default_max_transition;
                                
                                if(tpPtr->PinsTiming[graphIn[(*oi)].netName].fallTransition > lpPtr->default_max_transition)
                                        temp_slew_violation += tpPtr->PinsTiming[graphIn[(*oi)].netName].fallTransition - lpPtr->default_max_transition;
                                
                                Slack_Violation += temp_slack_violation;
                                Slew_Violation += temp_slew_violation;
                                
                                //for PO, the violation comes from its
                                //fan-in gates
                                graphIn[source((*oi), graphIn)].Slack_Violation += temp_slack_violation;                                
                                graphIn[source((*oi), graphIn)].Slew_Violation += temp_slew_violation;
                                graphIn[source((*oi), graphIn)].Slack_Redundancy += temp_slack_redundancy;
                        }
                        
                        //net name should be unique
                        temp += graphIn[(*oi)].netParasiticLoad;
                        LPCI_ = &(lpPtr->mapStandardLibraryCells[graphIn[target((*oi), graphIn)].cellName]); 
                        
                        for( it = LPCI_->pins.begin(); it != LPCI_->pins.end(); it++ )
                                if(it->name == graphIn[(*oi)].targetPinName)
                                        break;
                        
                        if(it != LPCI_->pins.end())
                                T_Output_Cap += (*it).capacitance;
                        else//should go back to the spec file for the output load
                        {
                                T_Output_Cap += 4; //we assume all case is
                                                   //4 for this benchmark set
                                //T_Output_Cap += sdcPtr->outputs_load[graphIn[(*oi)].netName];
                        }

                }
                
                T_Output_Cap += temp / boost::out_degree(in, graphIn);
                for( it = LPCI->pins.begin(); it != LPCI->pins.end(); it++ )
                        if(it->name == "o")
                                break;
                
                if(it == LPCI->pins.end())
                        cout<<"No Way"<<endl;
                
                if( (*it).maxCapacitance < T_Output_Cap){
                        Cap_Violation += T_Output_Cap - (*it).maxCapacitance;
                        graphIn[ in ].Cap_Violation += T_Output_Cap - (*it).maxCapacitance;
                }
        }
        
        int stat[8];
        memset(stat, 0, 8 * sizeof(int));
        int flag1, flag2, flag3;
        
        int vn = boost::num_vertices(graphIn) ;
        for(int i = 0; i < vn; i++)
        {
                flag1 = 0;
                flag2 = 0;
                flag3 = 0;
                
                if(graphIn[ i ].Cap_Violation > 0.0)
                {
                        flag1 = 1;
                        count_cap_vio++;
                }
                if(graphIn[ i ].Slack_Violation > 0.0)
                {
                        flag2 = 1;
                        count_slack_vio++;
                }
                if(graphIn[ i ].Slew_Violation > 0.0)
                {
                        flag3 = 1;
                        count_slew_vio++;
                }
                
                stat[flag1 + flag2 * 2 + flag3 * 4]++;
        }
        
        double Total_Violation = Slew_Violation + Slack_Violation + Cap_Violation;
        if(write_to_file)
        {
                /*out << Slack_Violation << "\t" << Slew_Violation 
                    << "\t" << Cap_Violation << "\t" << Total_Violation 
                    << "\t" << graphIn.accumTotalLeakage(lpPtr->mapStandardLibraryCells) 
                    << "\t" << count_slack_vio << "\t" << count_slew_vio << "\t" << count_cap_vio;*/
        }
        else
        {
                cout<<"From my Evaluation script....."<<endl;
                cout<< "Slack Violation is " << Slack_Violation << endl;
                cout<< "Slew Violation is " << Slew_Violation <<endl;
                cout<< "Cap Violation is " << Cap_Violation << endl;
                cout<< "Total Violation is " << Total_Violation << endl;
                cout << "The leakage power is : " << graphIn.accumTotalLeakage(lpPtr->mapStandardLibraryCells) << endl ;
        }
        
        int mode;
        if(Slack_Violation > Slew_Violation && Slack_Violation > Cap_Violation)
                graphIn.mode = 3;
        else if(Slew_Violation > Slack_Violation && Slew_Violation > Cap_Violation)
                graphIn.mode = 2;
        else if(Cap_Violation > Slack_Violation && Cap_Violation > Slew_Violation)
                graphIn.mode = 1;
        else
                graphIn.mode = 0;
        
        //out.close();
        
        return Total_Violation;
}



int main (int argc, char* argv[]) 
{
        if (argc != 3) {
		cout << "Usage: " << argv[0] << " benchmark_name library_file" << endl ;
		exit(0) ;
	}

	string contest_dir, benchmark_dir ;	
	contest_dir = argv[1]; 
	benchmark_dir = argv[2];
        cout<<"Benchmark directory is "<<benchmark_dir<<endl;
        
        clock_t startBenchmarkReading = clock() ;
        
	clock_t startReadStandardLibraryCell = clock() ;
	// 1. Read Standard Library Cell
	//------------------------------------------------------------------------------------
	string standardLibFile = contest_dir+"/lib/contest.lib" ;
	cout << "Start reading standard library cell ( " <<  standardLibFile << " )" << endl ;
	ExtendedLibParser lp (standardLibFile) ;
	lp.readStandardLibraryCell () ;
        lpPtr = &lp;
        //cout<<"Default Max Transition is " << lpPtr->default_max_transition <<endl;
        
        
        // 2. Read Sdc File
        string sdcFile = contest_dir + "/" + benchmark_dir + "/" + benchmark_dir + ".sdc" ;
        ExtendedSdcParser sdcp(sdcFile);
        sdcp.readSdcFile();
        sdcPtr = &sdcp;
	//------------------------------------------------------------------------------------
	clock_t endReadStandardLibraryCell = clock() ;
	
	
	clock_t startReadSpef = clock() ;
	// 3. Read Parasitic Load
	//-----------------------------------------------------------------------------------
	string spefFile = contest_dir + "/" + benchmark_dir + "/" + benchmark_dir + ".spef" ;
	cout << "Start reading parasitic load from " << spefFile << endl ;
	ExtendedSpefParser sp (spefFile) ;
	sp.readSpefFile () ;
	//-----------------------------------------------------------------------------------
	clock_t endReadSpef = clock() ;

	
	// 4. Initialize the circuit graph
	//-----------------------------------------------------------------------------------
	cout << "The graph is initialized..." << endl;
	CircuitGraph inputCircuit ;
        graphInPtr = &inputCircuit;
	//-----------------------------------------------------------------------------------

	
	clock_t startReadVerilog = clock() ;
	// 5. Read Verilog File
	//-----------------------------------------------------------------------------------
	string verilogFile = contest_dir + "/" + benchmark_dir + "/" + benchmark_dir + ".v" ;
	cout << "Start reading verilog file " << verilogFile << endl ;
	ExtendedVerilogParser vp (verilogFile) ;
        vpPtr = &vp;
        vp.readVerilogFile(inputCircuit, lp.mapStandardLibraryCells) ;
        cout << "End reading verilog file..." << endl ;
	//-----------------------------------------------------------------------------------
	clock_t endReadVerilog = clock() ;
        

	// 6. Udate edges in graph
	//-----------------------------------------------------------------------------------
	inputCircuit.updateConnectivity(vp.verilogConnectivity, sp.mapNetParasiticLoads) ;
        //-----------------------------------------------------------------------------------
        
	//inputCircuit.printGateProperty < string, gateProperty> (&gateProperty::cellName) ;
	
	cout << "The graph is ready for optimization..." << endl ;
        cout.precision(3) ;
	double leakageBefore = inputCircuit.accumTotalLeakage(lp.mapStandardLibraryCells) ;
	clock_t startOptimization = clock() ;
        
        /*Amir's part......................*/
        //6. Read .sdc file                                                                                                      
        // -----------------------------------------------------------------------------------
        //sdcp.updateOutputCap(inputCircuit) ;
        //sdcp.updateInputTime (inputCircuit, lp) ;

        //----------------------------------------------------------------------------------
        // Find the range of Output Capacitance for each gate and store
        // that in a file                                            
        //----------------------------------------------------------------------------------------------                          
        string capFile = contest_dir + "/" + benchmark_dir + "/" + benchmark_dir + "_capRange.txt" ;
        ofstream outCapacitance(capFile.c_str()) ;
        StoreOutCapacitance storeFunc ; 
        //inputCircuit.updateMinMaxOutputCap (lp, storeFunc, outCapacitance, true) ;
        //----------------------------------------------------------------------------------------------                          
        
        // fill each node in the circuit with library cells that have no
        // output violations                                        
        // inputCircuit.fillNoCapViolationCells (lp) ; // this is where the
        // run-time is exponentially increased
        /*Amir's part......................*/
        
	// 7. Initialize optimization, 
        // (1) size all cells to maximum power saving
	
	cout.precision(5) ;
	double timeStandard = (double)(endReadStandardLibraryCell - startReadStandardLibraryCell) / (double)CLOCKS_PER_SEC ;
	double timeSpef = (double)(endReadSpef - startReadSpef) / (double)CLOCKS_PER_SEC ;
	double timeVerilog = (double)(endReadVerilog - startReadVerilog) / (double)CLOCKS_PER_SEC ;
	
        cout << "--------------Run time---------------" << endl ;
	cout << "Reading Standard Library Cell: " <<  timeStandard << endl;
	cout << "Reading SPEF: " <<  timeSpef << endl;
	cout << "Reading Verilog: " << timeVerilog << endl;
	cout << "Total: " << timeStandard + timeSpef + timeVerilog << endl ;
	cout << "-------------------------------------" << endl ;
        
	/*_____________________________________________________________________End of benchmark parsing_______________________________________________________________*/
        /*_____________________________________________________________________Begin generating files for placement_______________________________________________________________*/
        
        // All file names needed for placement
        string AUX_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".aux";
        string NODES_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".nodes";
        string NETS_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".nets";
        string WTS_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".wts";
        string PL_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".pl";
        string SCL_file_name = contest_dir + "/Placement/" + benchmark_dir + "/" + benchmark_dir + ".scl";
        
        cout << " .aux file loc is " << AUX_file_name << endl;
        cout << " .nodes file loc is " << NODES_file_name << endl;
        cout << " .nets file loc is " << NETS_file_name << endl;
        cout << " .wts file loc is " << WTS_file_name << endl;
        cout << " .pl file loc is " << PL_file_name << endl;
        cout << " .scl file loc is " << SCL_file_name << endl;
        
        // Generating .aux file
        ofstream outAux(AUX_file_name.c_str());
        outAux << "RowBasedPlacement : " << benchmark_dir + ".nodes" + " " << benchmark_dir + ".nets" + " "
               << benchmark_dir + ".wts" + " " << benchmark_dir + ".pl" + " " << benchmark_dir + ".scl" + " " << endl;
        
        outAux.close();
        
        
        
        // Generating .nodes file
        ofstream outNodes(NODES_file_name.c_str());
        outNodes << "UCLA nodes 1.0" << endl;
        outNodes << "# File header with version information, etc.," << endl;
        outNodes << "# Benchmark Created by Min Li, Sep 2012" << endl;
        outNodes << endl;
        
        long verteces_count = 0;
        boost::graph_traits<CircuitGraph>::vertex_iterator vi, vi_end ;
	boost::graph_traits<CircuitGraph>::out_edge_iterator oi, oi_end;
        
        for (boost::tie(vi, vi_end) = boost::vertices(inputCircuit) ; vi != vi_end ; ++vi)
	{
                vertex_descriptor in = (*vi);
                if(inputCircuit[ in ].gateType != 0 && inputCircuit[ in ].gateType != 1)
                        verteces_count++;
        }
        
        outNodes << "NumNodes : " << verteces_count << endl;
        outNodes << "NumTerminals : 0" << endl;//assume every node is movable
        outNodes << endl;
        
        // node_name    width    height    move_type        
        for (boost::tie(vi, vi_end) = boost::vertices(inputCircuit) ; vi != vi_end ; ++vi)
	{
                vertex_descriptor in = (*vi);
                if(inputCircuit[ in ].gateType != 0 && inputCircuit[ in ].gateType != 1){
                        outNodes << inputCircuit[ in ].instanceName << "\t";
                        outNodes << "4\t" << "9\t" <<endl; // use "4" and "9" for now
                }
        }
        outNodes << endl;
        
        outNodes.close();
        


        // Generating .nets file
        ofstream outNets(NETS_file_name.c_str());
        outNets << "UCLA nets 1.0" << endl;
        outNets << "# File header with version information, etc.," << endl;
        outNets << "# Benchmark Created by Min Li, Sep 2012" << endl;
        outNets << endl;
        
        outNets << "NumNets : " << vp.verilogConnectivity.size() << endl;

        long Pin_Count = 0; // same as edge count in the graph
        for(int i = 0; i < vp.verilogConnectivity.size(); i++)
        {
                vp.verilogConnectivity[i].targetDirs.resize(vp.verilogConnectivity[i].targetVertices.size());//important
                Pin_Count += vp.verilogConnectivity[i].targetVertices.size();
        }
        outNets << "NumPins : " << Pin_Count << endl;
        outNets << endl;
        
        assignPinDir(inputCircuit);
        
        // NetDegree : degree_of_this_net net_name 
        // node_name pin_dir : pin_xoffset pin_yoffset
        for(int i = 0; i < vp.verilogConnectivity.size(); i++)
        {
                long temp = 0;
                if(vp.verilogConnectivity[i].sourcePin == "out")
                        temp = 1;
                else if(vp.verilogConnectivity[i].targetPins.size() == 1 && vp.verilogConnectivity[i].targetPins[0] == "in")
                        temp = vp.verilogConnectivity[i].targetVertices.size();
                
                outNets << "NetDegree : " <<  1 + vp.verilogConnectivity[i].targetVertices.size() - temp
                        << " " + vp.verilogConnectivity[i].netName << endl;
                
                //source vertex, should be only one
                if(vp.verilogConnectivity[i].sourcePin != "out")
                        outNets << inputCircuit[ vp.verilogConnectivity[i].sourceVertex ].instanceName + " "
                                << "O : " << vp.verilogConnectivity[i].sourceDir.first << " " + vp.verilogConnectivity[i].sourceDir.second << endl;
                
                //multiple target verteces, should exclude the dummy vertex created for PO
                if(!(vp.verilogConnectivity[i].targetPins.size() == 1 && vp.verilogConnectivity[i].targetPins[0] == "in")){
                        for(int j = 0; j < vp.verilogConnectivity[i].targetVertices.size(); j++)
                        {
                                outNets << inputCircuit[ vp.verilogConnectivity[i].targetVertices[j] ].instanceName + " "
                                        << "I : " << vp.verilogConnectivity[i].targetDirs[j].first 
                                        << " " + vp.verilogConnectivity[i].targetDirs[j].second << endl;
                        }
                }
        }
        
        outNets.close();
        

        
        // Generating .wts file, curretly supposed to be empty
        ofstream outWts(WTS_file_name.c_str());
        outWts << "UCLA nets 1.0" << endl;
        outWts << "# File header with version information, etc.," << endl;
        outWts << "# Benchmark Created by Min Li, Sep 2012" << endl;
        outWts << endl;
        
        outWts.close();

        
        
        // Generating .pl file
        ofstream outPl(PL_file_name.c_str());
        outPl << "UCLA nets 1.0" << endl;
        outPl << "# File header with version information, etc.," << endl;
        outPl << "# Benchmark Created by Min Li, Sep 2012" << endl;
        outPl << endl;
        outPl << "node_name\tll_xcord\tll_ycord\torientation\tmovetype" << endl;
        
        //movable blocks seem to all start at the original point
        for (boost::tie(vi, vi_end) = boost::vertices(inputCircuit) ; vi != vi_end ; ++vi)
	{
                vertex_descriptor in = (*vi) ;
                if(inputCircuit[ in ].gateType != 0 && inputCircuit[ in ].gateType != 1){
                        outPl << inputCircuit[ in ].instanceName << "\t";
                        outPl << "0\t" << "0\t: N\t" <<endl; // use "4" and "9" for now
                }
        }
        
        outPl.close();
        
        
        
        // Generating .scl file
        ofstream outScl(SCL_file_name.c_str());
        outScl << "UCLA nets 1.0" << endl;
        outScl << "# File header with version information, etc.," << endl;
        outScl << "# Benchmark Created by Min Li, Sep 2012" << endl;
        outScl << endl;
        
        const int NumRows = 1200;
        const int Height = 12;
        const int Coordinate = 100;
        const int SubrowOrigin = 6000;
        const int NumSites = Coordinate + NumRows * Height - SubrowOrigin - 50;//pure empierical based on observation 
        
        stringstream ss;
        ss << NumRows;
        outScl << "NumRows : " << ss.str() << endl;
        outScl << endl;
        
        //To be decide parameters: NumRows, Coordinate, subrowOrigin,
        //NumSites, Height
        for(int i = 0; i < NumRows; i++)
        {
                outScl << "CoreRow Horizontal" << endl;
                ss.str("");
                ss << Coordinate + i * 12;
                outScl << "Coordinate    :   " << ss.str() << endl;
                ss.str("");
                ss << Height;
                outScl << "Height        :   " << ss.str() << endl;
                outScl << "Sitewidth     :   1" << endl;
                outScl << "Sitespacing   :   1" << endl;
                outScl << "Siteorient    :   1" << endl;
                outScl << "Sitesymmetry  :   1" << endl;
                ss.str("");
                ss << SubrowOrigin;
                outScl << "SubrowOrigin  :   " << ss.str() << "\t"; 
                ss.str("");
                ss << NumSites;
                outScl << "NumSites : " << ss.str() << endl;
                outScl << "End" << endl;
        }
        
        outScl.close();
        
        cout << "All placement needed files have been generated." << endl;
        return 0;
}

